#!/usr/bin/env python
# encoding: utf-8
# @author: Lin Han
# @contact: voldemort22@126.com
# @file: deprecated_app.py
# @time: 2021/3/24 19:27
# @desc:
import json
import time

import requests
from fastapi import APIRouter, BackgroundTasks

from application.standard_part.crud import generate_standard_part_data
from application.standard_part.queryModels import StandardPartChangeSize, UploadStandardPartModel
from background.background_update import update_04
from cache.redis_pool import get_redis
from models.queryModels import MultipleConditionQueryStandardParts, UpdateOneStandardPart
from utils.mongo_tools import update_mongo_value, retrieve_one_mongo_value, create_one_mongo_value, delete_mongo_value, retrieve_all_mongo_values, standard_part_number_generator
from utils.oss.oss_tools import upload_file_to_oss
from utils.utils import save_json
from views.configs import *
from views.crud import separate_page, send_to_message_queue, keyword_search_standard_part, sort_redis_result

standard_part_router = APIRouter(
    prefix="/api/standard_part",
    tags=["standard_part"],
)


@standard_part_router.put("/v1/standard_part_show")
async def change_size(queryModel: StandardPartChangeSize):
    """
    关联中实时更改模型尺寸。首先会删除queryModel.number对应的原来的临时stl模型（如果有的话，这个模型是来自于之前对同一number的模型进行的操作而存在同一文件夹下），以免用户点击更新后看到错误尺寸的stl

    - :param queryModel:
    - :return:
    """
    temp_stl_oss_address = f"DOCenter_Dev/Pythonfiles/temp/standard_part/{queryModel.number}.stl"
    # print(delete_file_on_oss(temp_stl_oss_address))
    result = retrieve_all_mongo_values(
        filter_conditions={"number": queryModel.number},
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_PART_COLLECTION,
    )[0]

    print(result)
    result["file"]["jsonData"]["args"] = [i.dict() for i in queryModel.args]
    folder = "temp/standard_part"
    file_path = f"{folder}/{queryModel.number}.json5"
    # 写入文件
    save_json(result["file"]["jsonData"], file_path)
    upload_file_to_oss(local_file_name=file_path)
    result["file"]["tempJsonAliOssAddress"] = f"DOCenter_Dev/Pythonfiles/{file_path}"

    # 把标准零件的json格式模型（不是数据库里的数据）
    # send_to_message_queue(result, queue="temporary_json2stl")

    result["file"]["tempStlAliOssAddress"] = temp_stl_oss_address

    print(result)

    requests.request(
        method="post",
        url=f"http://{TEMPORARY_CONVERT_MACHINE_URL}:{TEMPORARY_CONVERT_MACHINE_PORT}/standard_part",
        # data=str(result, encoding="utf-8").encode('utf-8'),
        data=json.dumps(result)
    )
    # 判断在OSS上是否已经存在该文件了。不做这个判断了，过个15秒再返回数据吧。
    time.sleep(15)

    model = {"data": result, "status": 1}
    return model


@standard_part_router.get("/v1/standard_part_stl_file")
def get_standard_part_stl_file(number: str):
    """
    显示标准零件stl文件接口（给的是oss地址）

    - :param number: 编号
    - :return:
    """
    model = {"data": ""}
    # retrieve_one_mongo_value返回的是一个只有一个元素的列表，取第一个
    original_data = retrieve_one_mongo_value(
        number=number,
        collection_name=STANDARD_PART_COLLECTION,
    )
    if len(original_data) > 0:
        # 标准夹具现阶段是用stl文件来显示，后续考虑换成gltf
        model["data"] = original_data[0]["file"][STL_OSS_ADDRESS]
    model["status"] = 1
    return model


@standard_part_router.get("/v1/standard_part_json_file")
def get_standard_part_json_file(number: str):
    """
    下载 模型数据
    - :param number: 编号
    - :return:
    """
    model = {"data": ""}
    # retrieve_one_mongo_value返回的是一个只有一个元素的列表，取第一个
    original_data = retrieve_one_mongo_value(
        number=number,
        collection_name=STANDARD_PART_COLLECTION,
    )
    if len(original_data) > 0:
        model["data"] = {
            "name": original_data[0]['name'],
            'path': original_data[0]['file'][JSON_OSS_ADDRESS],
        }
        model["status"] = 1
    else:
        model["status"] = 0
    return model


@standard_part_router.post("/v3/standard_parts")
def multiple_condition_query_standard_parts_v3(queryModel: MultipleConditionQueryStandardParts, background_tasks: BackgroundTasks):
    """
    ## 多条件筛选查询标准零件v3版
    - :param queryModel:
    - :return:
    """
    redis_connection = get_redis(port=STANDARD_PART_REDIS_PORT)
    try:
        standard_part_number_list = redis_connection.get("standard_part")
        standard_part_number_list = json.loads(standard_part_number_list)
        standard_part_list = redis_connection.mget(*standard_part_number_list)
        result = [json.loads(i) for i in standard_part_list]
    except:
        result = retrieve_all_mongo_values({}, collection_name=STANDARD_PART_COLLECTION)
        background_tasks.add_task(update_04)

    result = keyword_search_standard_part(queryModel, result)
    if len(result) > 0:
        total = len(result)
        result = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        model = {
            "data": {
                "result": result,
                "total": total,
            },
            "status": 1,
        }
    else:
        model = {"data": {}, "status": 0}
    return model


@standard_part_router.get("/v3/standard_part")
def retrieve_standard_part_v3(number: str):
    """
    ## 返回一条标准零件的完整信息V3版
    返回值中多一个参数page，告知前端这条数据在第几个page（按pagesize为10的情况）。

    - :param number: 编号
    - :return:
    """
    redis_connection = get_redis(port=STANDARD_PART_REDIS_PORT)
    model = {"data": {}}

    # take out the data in redis
    try:
        try:
            standard_part = redis_connection.get(number)
            data = json.loads(standard_part)
        except:
            # if reach here then means no data in redis. Now go to mongo.
            data = retrieve_one_mongo_value(number, collection_name=STANDARD_PART_COLLECTION)[0]
            # then add it into redis
            redis_connection.set(number, json.dumps(data))
            standard_part_number_list = redis_connection.get("standard_part")
            standard_part_number_list = json.loads(standard_part_number_list)
            standard_part_number_list.append(number)
            redis_connection.set("standard_part", json.dumps(standard_part_number_list))
        model["data"] = data

        sort_redis_result(model=model, number=number, data_type="standard_part", redis_connection=redis_connection)
        model["status"] = 1
    except:
        model["status"] = 0
    return model


@standard_part_router.delete("/v3/standard_part")
def delete_standard_part_v3(number: str, background_task: BackgroundTasks):
    """
    ## 删除一条数据v3

    - :param number:
    - :return:
    """
    model = {"data": False}
    try:
        result = delete_mongo_value(
            number=number,
            collection_name=STANDARD_PART_COLLECTION,
        )
        background_task.add_task(update_04)
        if result.deleted_count > 0:
            model["data"] = True
            model["status"] = 1
        else:
            model["status"] = 0
    except:
        model["status"] = 0
    return model


@standard_part_router.put("/v3/standard_part")
def update_standard_part_v3(queryModel: UpdateOneStandardPart):
    """
    更新 标准零件的相关信息v3版本。

    - :param queryModel:
    - :return:
    """
    redis_connection = get_redis(port=STANDARD_PART_REDIS_PORT)
    model = {}
    updateInfo = {
        "$set": {
            "version": queryModel.version,
            "name": queryModel.name,
            "desc": queryModel.desc,
            "partFunction": queryModel.partFunction,
        }
    }
    update_mongo_value(
        {"number": queryModel.number},
        updateInfo,
        collection_name=STANDARD_PART_COLLECTION,
    )

    standard_part = retrieve_one_mongo_value(number=queryModel.number, collection_name=STANDARD_PART_COLLECTION)[0]

    redis_connection.set(queryModel.number, json.dumps(standard_part))
    model["data"] = True
    model["status"] = 1
    return model


@standard_part_router.post("/v3/standard_part")
def upload_v3(queryModel: UploadStandardPartModel):
    """
    ## 上传标准零件模型v3
    :param request:
    :param queryModel:
    :return:
    """
    redis_connection = get_redis(port=STANDARD_PART_REDIS_PORT)
    number = standard_part_number_generator()
    model_data = generate_standard_part_data(
        number,
        file_path=queryModel.jsonAliOssAddress,
        desc=queryModel.desc,
        version=queryModel.version,
        category=queryModel.category,
    )

    redis_connection.set(model_data["number"], json.dumps(model_data))

    create_one_mongo_value(model_data, database_name=MONGO_DATABASE_NAME, collection_name=STANDARD_CLAMP_COLLECTION)
    send_to_message_queue(number, queue=STANDARD_PART_QUEUE)

    model = {"data": number, "status": 1}
    return model


@standard_part_router.get("/v2/standard_part_config")
async def get_standard_part_version():
    """
    ## 获取 标准零件 所有的版本号
    原standard_part_version接口

    - :return:
    """
    redis_connection = get_redis(port=STANDARD_PART_REDIS_PORT)
    try:
        standard_part_config = redis_connection.get("standard_part_config")
        config_data = json.loads(standard_part_config)
    except:
        config_data = retrieve_all_mongo_values(
            {"type": CONFIG_DATA_STANDARD_PART_TYPE},
            collection_name="config",
        )[0][CONFIG_DATA]
        # 把mongo中查到的数据set到redis数据库中
        redis_connection.set("standard_part_config", json.dumps(config_data))

    model = {"data": config_data, "status": 1}
    return model
